#encoding:utf8
from werkzeug.utils import secure_filename
from flask import Flask, render_template, jsonify, request, redirect,url_for,flash
import matplotlib.pyplot as plt  # plt 用于显示图片
import matplotlib.image as mpimg  # mpimg 用于读取图片
import time
import cv2
import os
import base64
from flask import session,Response,json
from  MyHelper import  MyHelper
import scipy as sp

app = Flask(__name__)

app.secret_key = 'test'

UPLOAD_FOLDER = 'upload'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
basedir = os.path.abspath(os.path.dirname(__file__))
ALLOWED_EXTENSIONS = set(['png', 'jpeg', 'jpg', 'JPG', 'PNG', 'gif', 'GIF'])#允许的上传格式

#判断是否相交
def xj(xa,ya, xb, yb,  xc,  yc,  xd,  yd,  pic1x,  pic1y,  pic2x,  pic2y):
   #标准化
    xa = xa / pic1x
    xc = xc / pic1x
    ya = ya / pic1y
    yc = yc / pic1y
   #BD点的横纵坐标
    xb = 1 + xb / pic2x
    xd = 1 + xd / pic2x
    yb = 1 + yb / pic2y
    yd = 1 + yd / pic2y
   #向量计算的准备
    xab = xb - xa
    yab = yb - ya
    xac = xc - xa
    yac = yc - ya
    xad = xd - xa
    yad = yd - ya
   #向量的叉乘
    abxac = xab * yac - xac * yab
    abxad = xab * yad - xad * yab
   #如果向量的叉乘小于零即为相交
    if abxac * abxad <= 0 :
      #  print("xiangjiao")
        return 1
    #不相交
    else:
      #  print("buxiangjiao")
        return 0




# 用于判断文件后缀
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS


#主页页面
@app.route('/test.html')
def test():
    return render_template("test.html")

#导航页面
@app.route('/')
def homepage():
    return render_template("homepage.html")
#博物馆页面
@app.route('/museum.html')
def museum():
    return render_template("museum.html")

#注册页面
@app.route('/register/',methods=['GET','POST'])
def register():
    if request.method == 'POST':
        print("post")
        #获取前端传递的数据
        uname = request.form.get('uname')#获取用户名
        upwd = request.form.get('upwd')#获取密码
        city = request.form.get('city')#获取城市
        # tel = request.form.get('tel')
        #将数据添加到数据库
        helper= MyHelper()
        sql='insert into user_tb(username,password,city) values(%s,%s,%s)'
        params =[uname,upwd,city]
        rows = helper.executeUpdate(sql,params)#成功操作的行数

        #进行判断是否添加成功
        if rows > 0:
            return redirect(url_for("userLogin"))
            #return "成功"
        else:
            #失败则返回注册页面
            flash("用户注册失败")
            return render_template('register.html')
    else:
        return  render_template("register.html")



@app.route('/userLogin/',methods=['GET','POST'])
def userLogin():
    if request.method == 'POST':
        uname = request.form.get('uname')
        upwd = request.form.get('upwd')

        #到数据库中进行查询
        helper = MyHelper()
        sql="select * from user_tb where username=%s and password =%s"
        params=[uname,upwd]
        result = helper.executeQuery(sql,params)#读取result结果

        if result != ():
            #将用户id保存到会话中，判断用户登录
            session['u_id'] = result[0][0]
            #在程序界面中打印，用来判断
            print("登陆成功")

            return redirect(url_for("homepage"))
            # return render_template('homepage.html')
        else:#登录失败
            print("用户名或者密码不正确")
            return render_template('userLogin.html')

    else:
        return render_template("userLogin.html")

# @app.route("/searchpaint")
# def searchpaint():
#     return render_template("searchpaint.html")


#根据名字寻找图片
@app.route('/search/',methods=['GET','POST'])
def search():
    print(request.method)
    if request.method == 'POST':
        #print("进入post"),测试是否进入post
        paintname = request.form.get('chinaname') #获取名字
        #插入数据库
        helper = MyHelper()
        sql = "select * from painter_tb where chinaname=%s "
        params = [paintname]
        result = helper.executeQuery(sql, params)
        #print(result)

        if result != ():#如果结果不是空，返回查询结果
            return render_template('searchresult.html',result = result)
        else:#结果为空返回没有画面界面
            return render_template('nopaint.html')
    else:
        return render_template("searchpaint.html")


@app.route('/changepsw/',methods=['GET','POST'])
def changepsw():
    #print(request.method)判断是获取的method
    if request.method == 'POST':
        #print("进入post")测试是否进入post
        uname = request.form.get('uname')#获取旧的用户名
        oldpsw = request.form.get('oldpsw')#获取旧的密码
        newpsw = request.form.get('newpsw')#获取新的密码

        helper = MyHelper()#连接数据库
        sql = "select * from user_tb where username=%s and password = %s "
        params = [uname,oldpsw]
        result = helper.executeQuery(sql, params)
        #判断是否密码正确

        if result != ():
            #print(result)测试result
            helper2 = MyHelper()
            sql = "delete from user_tb where username = %s"
            #删除旧密码所在行
            params = [oldpsw]
            drow = helper2.executeUpdate(sql,params)
            #print(drow) 测试删除行数
            helper3 = MyHelper()
            sql='insert into user_tb(username,password,city) values(%s,%s,%s)'
            #插入更改过后的用户名城市，密码新增
            params =[result[0][1],newpsw,result[0][3]]
            srow = helper.executeUpdate(sql,params)
            #更改的行数

            print(srow)
            return render_template("userLogin.html")
        else:
            return render_template("register.html")

    else:
        return render_template("changepsw.html")








# 用于测试上传，稍后用到
@app.route('/identify.html',methods=['GET'],strict_slashes=False)
def identify():
    #判断用户登录的状态
    uid = session.get('u_id')
    #没有登录不能跳转到识别页面，回到注册页面
    if uid  :
        return render_template('identify.html')#回到识别页面
    else:
        return render_template('userLogin.html')#回到登录页面

# 上传文件
@app.route('/identify.html',methods=['POST'],strict_slashes=False)
def api_upload():
    #获取文件路径
    file_dir = os.path.join(basedir, app.config['UPLOAD_FOLDER'])
    #判断上传的文件路径
    if not os.path.exists(file_dir):
        os.makedirs(file_dir)
    f = request.files['file']  # 从表单的file字段获取文件，file为该表单的name值

    if f and allowed_file(f.filename):  # 判断是否是允许上传的文件类型
        fname = secure_filename(f.filename)
        print(fname)           #测试fname
        ext = fname.rsplit('.', 1)[1]  # 获取文件后缀
        unix_time = int(time.time())
        new_filename = str(unix_time)+'.'+ext  # 修改了上传的文件名
        f.save(os.path.join(basedir, new_filename))  #保存文件到upload目录
        #token = base64.b64encode(new_filename)
        # load
        #img = mpimg.imread(os.path.join(file_dir, new_filename))
        # print(os.path.join(file_dir, new_filename))
        # print(file_dir)
        # file_dir.replace("\\","//")
        # print(file_dir)

        img1 = cv2.imread(new_filename,0)

        img4 = cv2.imread('C://pic//1.jpg', 0)
        img5 = cv2.imread('C://pic//2.jpg', 0)
        img6 = cv2.imread('C://pic//3.jpg', 0)
        img7 = cv2.imread('C://pic//4.jpg', 0)
        img8 = cv2.imread('C://pic//5.jpg', 0)
        img9 = cv2.imread('C://pic//6.jpg', 0)
        img10 = cv2.imread('C://pic//7.jpg', 0)
        img11 = cv2.imread('C://pic//8.jpg', 0)
        img12 = cv2.imread('C://pic//9.jpg', 0)
        img13 = cv2.imread('C://pic//10.jpg', 0)
        img14 = cv2.imread('C://pic//11.jpg', 0)
        img15 = cv2.imread('C://pic//12.jpg', 0)
        img16 = cv2.imread('C://pic//13.jpg', 0)
        img17 = cv2.imread('C://pic//14.jpg', 0)
        img18 = cv2.imread('C://pic//15.jpg', 0)
        img19 = cv2.imread('C://pic//16.jpg', 0)
        img20 = cv2.imread('C://pic//17.jpg', 0)
        img21 = cv2.imread('C://pic//18.jpg', 0)
        img22 = cv2.imread('C://pic//19.jpg', 0)
        img23 = cv2.imread('C://pic//20.jpg', 0)
        img24 = cv2.imread('C://pic//21.jpg', 0)
        img25 = cv2.imread('C://pic//22.jpg', 0)
        img26 = cv2.imread('C://pic//23.jpg', 0)
        img27 = cv2.imread('C://pic//24.jpg', 0)
        img28 = cv2.imread('C://pic//25.jpg', 0)
        img29 = cv2.imread('C://pic//26.jpg', 0)
        img30 = cv2.imread('C://pic//27.jpg', 0)
        img31 = cv2.imread('C://pic//28.jpg', 0)
        img32 = cv2.imread('C://pic//29.jpg', 0)
        img33 = cv2.imread('C://pic//30.jpg', 0)


        shuju = []


        shuju.append(img4)
        shuju.append(img5)
        shuju.append(img6)
        shuju.append(img7)
        shuju.append(img8)
        shuju.append(img9)
        shuju.append(img10)
        shuju.append(img11)
        shuju.append(img12)
        shuju.append(img13)
        shuju.append(img14)
        shuju.append(img15)
        shuju.append(img16)
        shuju.append(img17)
        shuju.append(img19)
        shuju.append(img18)
        shuju.append(img20)
        shuju.append(img21)
        shuju.append(img22)
        shuju.append(img23)
        shuju.append(img24)
        shuju.append(img25)
        shuju.append(img26)
        shuju.append(img27)
        shuju.append(img28)
        shuju.append(img29)
        shuju.append(img30)
        shuju.append(img31)
        shuju.append(img32)
        shuju.append(img33)



        #print(len(shuju))
        #打印数据列表的长度，用来测试
        result = 0  #初始化结果，结果从1开始
        temp_pipei = 0  #初始化匹配转换算子
        temp_xiangjiao = 100 #最高，初始相交个数为100
        numberofse = 0  #计算到了第几个

        sift = cv2.xfeatures2d.SIFT_create() #创造sift对象
        kp1, des1 = sift.detectAndCompute(img1, None)
        FLANN_INDEX_KDTREE = 0  #初始化参数
        index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=3)
        search_params = dict(checks=50)  # or pass empty dictionary
        flann = cv2.FlannBasedMatcher(index_params, search_params)
        #匹配点

        #开始对数据库中的点进行匹配
        for se in shuju:
            # Apply ratio test
            kp2, des2 = sift.detectAndCompute(se, None)
            #用flann方法寻找匹配点
            matches = flann.knnMatch(des1, des2, k=2)
            #所有匹配点
            good = []
            #初始化good，匹配的好点的列表
            #开始筛选好点打印匹配点的个数
            print(len(matches))
            for m, n in matches:
                if m.distance < 0.2 * n.distance:
                    good.append(m)
            #如果两点距离小于阈值，不纳入好的匹配点
            h1, w1 = img1.shape[:2]#读取上传图片的大小
            h2, w2 = se.shape[:2]#读取当前匹配图片的大小
            view = sp.zeros((max(h1, h2), w1 + w2, 3), sp.uint8)#建立空白的图像，可以包括两幅图片
            view[:h1, :w1, 0] = img1 #把view的左部分放入img
            view[:h2, w1:, 0] = se #把view的做部分放入当前识别的图像
            view[:, :, 1] = view[:, :, 0]#灰度图
            view[:, :, 2] = view[:, :, 0]

            xiangjiaogeshu = 0
            #初始化两幅图的匹配点连线的相交个数
            #为了优化算法，如果好的匹配点个数为零，跳过相交的步骤以减少运行时间
            if len(good)!= 0: #判断匹配点个数
                for m in good:
                    for n in good: #在good中进行遍历
                        if n != m: #如果两点重合一定相交，所以排除两点重合判断相交的情况
                            if (xj(int(kp1[m.queryIdx].pt[0]), int(kp1[m.queryIdx].pt[1]), int(kp2[m.trainIdx].pt[0]),
                                   int(kp2[m.trainIdx].pt[1]), int(kp1[n.queryIdx].pt[0]), int(kp1[n.queryIdx].pt[1]),
                                   int(kp2[n.trainIdx].pt[0]), int(kp2[n.trainIdx].pt[1]), w1, h1, w2, h2)) == 1:
                                xiangjiaogeshu += 1
            #cv2.imshow("view", view)，测试xj函数是否正常运行
            numberofse = numberofse + 1  #当前匹配的序号
            print("第", numberofse, "张匹配数", len(good), "相交数", xiangjiaogeshu)
            #打印识别结果，判断进程运行速度
            #判断识别结果
            #如果当前识别的点 匹配个数比上一个点多而且相交个数比上一个点少，则记录当前点
            if temp_pipei < len(good) and temp_xiangjiao > xiangjiaogeshu:
                temp_pipei = len(good)
                temp_xiangjiao = xiangjiaogeshu
                result = numberofse  #记录当前点

        # if temp_pipei<5 or temp_xiangjiao > 5:
        #     print("无匹配结果")
        # else:
        rid = result
        helper2 = MyHelper()
        #寻找匹配结果的信息
        sql = "select * from painter_tb where id = %s"
        params = [rid]
        result = helper2.executeQuery(sql, params)
        #判断result的值
        if result != ():#有搜索结果
            return render_template('result.html', result=result)  # 跳转到结果界面
        else:#没有搜索结果
            return render_template('noidentify.html')


    else:
        #return jsonify({"errno": 1001, "errmsg": "failed"})
        return "s" #测试get方法是否执行




if __name__ == '__main__':
    app.run(host = "10.0.0.4",port = 5555)
